using Microsoft.AspNetCore.SignalR;
using WebRtcProject.Models;
using WebRtcProject.Models.Messages;
using WebRtcProject.Services;
using System.Text.Json;

namespace WebRtcProject.Hubs
{
    public class SignalingHub : Hub
    {
        private readonly IRoomService _roomService;
        private readonly IUserService _userService;
        private readonly IRabbitMQService _rabbitMQService;
        private readonly ILogger<SignalingHub> _logger;

        public SignalingHub(IRoomService roomService, IUserService userService, IRabbitMQService rabbitMQService, ILogger<SignalingHub> logger)
        {
            _roomService = roomService;
            _userService = userService;
            _rabbitMQService = rabbitMQService;
            _logger = logger;
        }

        // 用户连接
        public override async Task OnConnectedAsync()
        {
            _logger.LogInformation("User connected: {ConnectionId} from {IPAddress}", 
                Context.ConnectionId, Context.GetHttpContext()?.Connection?.RemoteIpAddress?.ToString());
            await base.OnConnectedAsync();
        }

        // 用户断开连接
        public override async Task OnDisconnectedAsync(Exception? exception)
        {
            try
            {
                var user = await _userService.GetUserByConnectionIdAsync(Context.ConnectionId);
                if (user != null)
                {
                    // 从房间中移除用户
                    if (!string.IsNullOrEmpty(user.RoomId))
                    {
                        await _roomService.RemoveUserFromRoomAsync(user.RoomId, user.Id);
                        await Groups.RemoveFromGroupAsync(Context.ConnectionId, user.RoomId);
                        
                        // 通知房间内其他用户
                        await Clients.Group(user.RoomId).SendAsync("UserLeft", new { UserId = user.Id, UserName = user.Name });
                        
                        // 发布用户离开事件
                        var leaveEvent = UserEventMessage.UserLeft(user.Id, user.Name, user.RoomId);
                        await _rabbitMQService.PublishUserEventAsync(leaveEvent);
                    }

                    // 删除用户
                    await _userService.DeleteUserAsync(user.Id);
                    _logger.LogInformation("User disconnected: {UserId}, Name: {UserName}", user.Id, user.Name);
                }
                else
                {
                    _logger.LogWarning("User disconnected but not found in service: {ConnectionId}", Context.ConnectionId);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error handling user disconnection: {ConnectionId}", Context.ConnectionId);
            }

            await base.OnDisconnectedAsync(exception);
        }

        // 用户加入
        public async Task JoinUser(string userName)
        {
            _logger.LogInformation("JoinUser called: userName='{UserName}', connectionId='{ConnectionId}'", userName, Context.ConnectionId);
            
            try
            {
                // 验证输入
                if (string.IsNullOrWhiteSpace(userName))
                {
                    _logger.LogWarning("JoinUser failed: empty username from {ConnectionId}", Context.ConnectionId);
                    await Clients.Caller.SendAsync("Error", "用户名不能为空");
                    return;
                }

                if (userName.Length > 50)
                {
                    _logger.LogWarning("JoinUser failed: username too long from {ConnectionId}", Context.ConnectionId);
                    await Clients.Caller.SendAsync("Error", "用户名长度不能超过50个字符");
                    return;
                }

                _logger.LogDebug("Creating user: userName='{UserName}', connectionId='{ConnectionId}'", userName.Trim(), Context.ConnectionId);
                var user = await _userService.CreateUserAsync(userName.Trim(), Context.ConnectionId);
                _logger.LogDebug("User created successfully: userId='{UserId}', userName='{UserName}'", user.Id, user.Name);
                
                _logger.LogDebug("Sending UserJoined event to caller: userId='{UserId}', userName='{UserName}'", user.Id, user.Name);
                await Clients.Caller.SendAsync("UserJoined", new { UserId = user.Id, UserName = user.Name });
                _logger.LogInformation("UserJoined event sent successfully to {ConnectionId}", Context.ConnectionId);
                
                _logger.LogInformation("User {UserName} joined with ID {UserId} from IP {IPAddress}", 
                    userName, user.Id, Context.GetHttpContext()?.Connection?.RemoteIpAddress?.ToString());

                // 发布用户加入事件到RabbitMQ
                var userEvent = UserEventMessage.UserJoined(user.Id, user.Name);
                //await _rabbitMQService.PublishUserEventAsync(userEvent);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error joining user {UserName} from connection {ConnectionId}", userName, Context.ConnectionId);
                await Clients.Caller.SendAsync("Error", "加入系统失败，请重试");
            }
        }

        // 创建房间
        public async Task CreateRoom(string roomName, int maxUsers)
        {
            _logger.LogInformation("CreateRoom called: roomName='{RoomName}', maxUsers={MaxUsers}, connectionId='{ConnectionId}'", 
                roomName, maxUsers, Context.ConnectionId);
            
            try
            {
                // 验证输入
                if (string.IsNullOrWhiteSpace(roomName))
                {
                    _logger.LogWarning("Empty room name provided");
                    await Clients.Caller.SendAsync("Error", "房间名称不能为空");
                    return;
                }

                if (roomName.Length > 100)
                {
                    _logger.LogWarning("Room name too long: {Length} characters", roomName.Length);
                    await Clients.Caller.SendAsync("Error", "房间名称长度不能超过100个字符");
                    return;
                }

                if (maxUsers < 2 || maxUsers > 50)
                {
                    _logger.LogWarning("Invalid maxUsers value: {MaxUsers}", maxUsers);
                    await Clients.Caller.SendAsync("Error", "房间最大用户数应在2-50之间");
                    return;
                }

                // 检查用户是否已经加入系统
                var user = await _userService.GetUserByConnectionIdAsync(Context.ConnectionId);
                if (user == null)
                {
                    await Clients.Caller.SendAsync("Error", "请先加入系统");
                    return;
                }

                _logger.LogInformation("Creating room with RoomService...");
                var room = await _roomService.CreateRoomAsync(roomName.Trim(), maxUsers);
                
                _logger.LogInformation("Room created successfully: Id={RoomId}, Name={RoomName}, MaxUsers={MaxUsers}", 
                    room?.Id, room?.Name, room?.MaxUsers);
                
                if (room == null)
                {
                    _logger.LogError("RoomService returned null room object");
                    await Clients.Caller.SendAsync("Error", "创建房间失败：服务返回空对象");
                    return;
                }
                
                if (string.IsNullOrEmpty(room.Id))
                {
                    _logger.LogError("Room created but Id is null or empty");
                    await Clients.Caller.SendAsync("Error", "创建房间失败：房间ID为空");
                    return;
                }
                
                if (string.IsNullOrEmpty(room.Name))
                {
                    _logger.LogError("Room created but Name is null or empty");
                    await Clients.Caller.SendAsync("Error", "创建房间失败：房间名称为空");
                    return;
                }

                // 自动让创建者加入房间
                _logger.LogInformation("Adding room creator {UserId} to room {RoomId}", user.Id, room.Id);
                var joinSuccess = await _roomService.AddUserToRoomAsync(room.Id, user);
                if (joinSuccess)
                {
                    await Groups.AddToGroupAsync(Context.ConnectionId, room.Id);
                    _logger.LogInformation("Room creator {UserId} successfully joined room {RoomId}", user.Id, room.Id);
                    
                    // 发送房间创建成功事件
                    await Clients.Caller.SendAsync("RoomCreated", new { RoomId = room.Id, RoomName = room.Name });
                    
                    // 发送加入房间成功事件（创建者自动加入）
                    await Clients.Caller.SendAsync("JoinedRoom", new { RoomId = room.Id, Users = new object[0] });
                    
                    _logger.LogInformation("Room created and creator joined: {RoomId}, Name: {RoomName}, Creator: {UserId}", 
                        room.Id, room.Name, user.Id);
                }
                else
                {
                    _logger.LogError("Failed to add room creator {UserId} to room {RoomId}", user.Id, room.Id);
                    await Clients.Caller.SendAsync("Error", "房间创建成功但加入失败");
                    return;
                }

                // 发布房间创建事件到 RabbitMQ
                try
                {
                    var roomEvent = RoomEventMessage.RoomCreated(room.Id, room.Name, room.MaxUsers);
                    await _rabbitMQService.PublishRoomEventAsync(roomEvent);
                    _logger.LogInformation("Room event published successfully for room {RoomId}", room.Id);
                }
                catch (Exception rabbitEx)
                {
                    _logger.LogWarning(rabbitEx, "Failed to publish room event for room {RoomId}, but room creation succeeded", room.Id);
                    // 不抛出异常，允许房间创建成功
                }
                
                // 发布用户加入房间事件到 RabbitMQ
                try
                {
                    var joinEvent = UserEventMessage.UserJoinedRoom(user.Id, user.Name, room.Id);
                    await _rabbitMQService.PublishUserEventAsync(joinEvent);
                    _logger.LogInformation("User join room event published for user {UserId} in room {RoomId}", user.Id, room.Id);
                }
                catch (Exception rabbitEx)
                {
                    _logger.LogWarning(rabbitEx, "Failed to publish user join room event for user {UserId} in room {RoomId}", user.Id, room.Id);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating room {RoomName} from connection {ConnectionId}", roomName, Context.ConnectionId);
                await Clients.Caller.SendAsync("Error", "创建房间失败，请重试");
            }
        }

        // 加入房间
        public async Task JoinRoom(string roomId)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(roomId))
                {
                    await Clients.Caller.SendAsync("Error", "房间ID不能为空");
                    return;
                }

                var user = await _userService.GetUserByConnectionIdAsync(Context.ConnectionId);
                if (user == null)
                {
                    await Clients.Caller.SendAsync("Error", "用户未找到，请先加入系统");
                    return;
                }

                var success = await _roomService.AddUserToRoomAsync(roomId, user);
                if (success)
                {
                    await Groups.AddToGroupAsync(Context.ConnectionId, roomId);
                    
                    // 获取房间用户列表
                    var roomUsers = await _roomService.GetRoomUsersAsync(roomId);
                    var otherUsers = roomUsers.Where(u => u.Id != user.Id).Select(u => new { u.Id, u.Name }).ToList();
                    
                    // 通知调用者房间信息
                    await Clients.Caller.SendAsync("JoinedRoom", new { RoomId = roomId, Users = otherUsers });
                    
                    // 通知房间内其他用户有新用户加入
                    await Clients.Group(roomId).SendAsync("UserJoined", new { UserId = user.Id, UserName = user.Name });
                    
                    _logger.LogInformation("User {UserId} ({UserName}) joined room {RoomId}", user.Id, user.Name, roomId);

                    // 发布用户加入房间事件
                    var joinEvent = UserEventMessage.UserJoinedRoom(user.Id, user.Name, roomId);
                    await _rabbitMQService.PublishUserEventAsync(joinEvent);
                }
                else
                {
                    await Clients.Caller.SendAsync("Error", "加入房间失败，房间可能已满或不存在");
                    _logger.LogWarning("Failed to add user {UserId} to room {RoomId}", user.Id, roomId);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error joining room {RoomId} from connection {ConnectionId}", roomId, Context.ConnectionId);
                await Clients.Caller.SendAsync("Error", "加入房间失败，请重试");
            }
        }

        // 离开房间
        public async Task LeaveRoom()
        {
            try
            {
                var user = await _userService.GetUserByConnectionIdAsync(Context.ConnectionId);
                if (user != null && !string.IsNullOrEmpty(user.RoomId))
                {
                    var roomId = user.RoomId;
                    await _roomService.RemoveUserFromRoomAsync(roomId, user.Id);
                    await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomId);
                    
                    // 通知房间内其他用户
                    await Clients.Group(roomId).SendAsync("UserLeft", new { UserId = user.Id, UserName = user.Name });
                    
                    await Clients.Caller.SendAsync("LeftRoom", new { RoomId = roomId });
                    _logger.LogInformation("User {UserId} ({UserName}) left room {RoomId}", user.Id, user.Name, roomId);

                    // 发布用户离开房间事件
                    var leaveEvent = UserEventMessage.UserLeftRoom(user.Id, user.Name, roomId);
                    await _rabbitMQService.PublishUserEventAsync(leaveEvent);
                }
                else
                {
                    await Clients.Caller.SendAsync("Error", "您当前不在任何房间中");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error leaving room from connection {ConnectionId}", Context.ConnectionId);
                await Clients.Caller.SendAsync("Error", "离开房间失败，请重试");
            }
        }

        // 发送WebRTC Offer
        public async Task SendOffer(string targetUserId, object offer)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(targetUserId))
                {
                    await Clients.Caller.SendAsync("Error", "目标用户ID不能为空");
                    return;
                }

                if (offer == null)
                {
                    await Clients.Caller.SendAsync("Error", "Offer数据不能为空");
                    return;
                }

                var sender = await _userService.GetUserByConnectionIdAsync(Context.ConnectionId);
                if (sender == null)
                {
                    await Clients.Caller.SendAsync("Error", "发送者用户未找到");
                    return;
                }

                var targetUser = await _userService.GetUserAsync(targetUserId);
                if (targetUser == null)
                {
                    await Clients.Caller.SendAsync("Error", "目标用户未找到");
                    return;
                }

                // 检查两用户是否在同一房间
                if (sender.RoomId != targetUser.RoomId || string.IsNullOrEmpty(sender.RoomId))
                {
                    await Clients.Caller.SendAsync("Error", "您和目标用户不在同一房间中");
                    return;
                }

                await Clients.Client(targetUser.ConnectionId).SendAsync("ReceiveOffer", new 
                { 
                    From = sender.Id, 
                    FromName = sender.Name,
                    Offer = offer 
                });
                
                _logger.LogInformation("WebRTC Offer sent from {SenderId} ({SenderName}) to {TargetId} ({TargetName}) in room {RoomId}", 
                    sender.Id, sender.Name, targetUserId, targetUser.Name, sender.RoomId);

                // 发布信令事件
                var signalingEvent = SignalingEventMessage.OfferSent(sender.Id, targetUserId, sender.RoomId);
                await _rabbitMQService.PublishSignalingEventAsync(signalingEvent);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error sending offer from {ConnectionId} to {TargetUserId}", Context.ConnectionId, targetUserId);
                await Clients.Caller.SendAsync("Error", "发送通话邀请失败，请重试");
            }
        }

        // 发送WebRTC Answer
        public async Task SendAnswer(string targetUserId, object answer)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(targetUserId))
                {
                    await Clients.Caller.SendAsync("Error", "目标用户ID不能为空");
                    return;
                }

                if (answer == null)
                {
                    await Clients.Caller.SendAsync("Error", "Answer数据不能为空");
                    return;
                }

                var sender = await _userService.GetUserByConnectionIdAsync(Context.ConnectionId);
                if (sender == null)
                {
                    await Clients.Caller.SendAsync("Error", "发送者用户未找到");
                    return;
                }

                var targetUser = await _userService.GetUserAsync(targetUserId);
                if (targetUser == null)
                {
                    await Clients.Caller.SendAsync("Error", "目标用户未找到");
                    return;
                }

                await Clients.Client(targetUser.ConnectionId).SendAsync("ReceiveAnswer", new 
                { 
                    From = sender.Id, 
                    FromName = sender.Name,
                    Answer = answer 
                });
                
                _logger.LogInformation("WebRTC Answer sent from {SenderId} ({SenderName}) to {TargetId} ({TargetName}) in room {RoomId}", 
                    sender.Id, sender.Name, targetUserId, targetUser.Name, sender.RoomId);

                // 发布信令事件
                var signalingEvent = SignalingEventMessage.AnswerSent(sender.Id, targetUserId, sender.RoomId);
                await _rabbitMQService.PublishSignalingEventAsync(signalingEvent);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error sending answer from {ConnectionId} to {TargetUserId}", Context.ConnectionId, targetUserId);
                await Clients.Caller.SendAsync("Error", "发送通话应答失败，请重试");
            }
        }

        // 发送ICE Candidate
        public async Task SendIceCandidate(string targetUserId, object candidate)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(targetUserId))
                {
                    await Clients.Caller.SendAsync("Error", "目标用户ID不能为空");
                    return;
                }

                if (candidate == null)
                {
                    await Clients.Caller.SendAsync("Error", "ICE候选者数据不能为空");
                    return;
                }

                var sender = await _userService.GetUserByConnectionIdAsync(Context.ConnectionId);
                if (sender == null)
                {
                    await Clients.Caller.SendAsync("Error", "发送者用户未找到");
                    return;
                }

                var targetUser = await _userService.GetUserAsync(targetUserId);
                if (targetUser == null)
                {
                    await Clients.Caller.SendAsync("Error", "目标用户未找到");
                    return;
                }

                await Clients.Client(targetUser.ConnectionId).SendAsync("ReceiveIceCandidate", new 
                { 
                    From = sender.Id, 
                    Candidate = candidate 
                });
                
                _logger.LogDebug("ICE Candidate sent from {SenderId} to {TargetId} in room {RoomId}", 
                    sender.Id, targetUserId, sender.RoomId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error sending ICE candidate from {ConnectionId} to {TargetUserId}", Context.ConnectionId, targetUserId);
                await Clients.Caller.SendAsync("Error", "发送连接信息失败");
            }
        }

        // 通话结束
        public async Task EndCall(string targetUserId)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(targetUserId))
                {
                    await Clients.Caller.SendAsync("Error", "目标用户ID不能为空");
                    return;
                }

                var sender = await _userService.GetUserByConnectionIdAsync(Context.ConnectionId);
                if (sender == null)
                {
                    await Clients.Caller.SendAsync("Error", "发送者用户未找到");
                    return;
                }

                var targetUser = await _userService.GetUserAsync(targetUserId);
                if (targetUser != null)
                {
                    await Clients.Client(targetUser.ConnectionId).SendAsync("CallEnded", new 
                    { 
                        From = sender.Id, 
                        FromName = sender.Name 
                    });
                }

                await Clients.Caller.SendAsync("CallEnded", new { TargetUserId = targetUserId });
                _logger.LogInformation("Call ended between {SenderId} and {TargetId}", sender.Id, targetUserId);

                // 发布通话结束事件
                var callEvent = SignalingEventMessage.CallEnded(sender.Id, targetUserId, sender.RoomId);
                await _rabbitMQService.PublishSignalingEventAsync(callEvent);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error ending call from {ConnectionId} to {TargetUserId}", Context.ConnectionId, targetUserId);
                await Clients.Caller.SendAsync("Error", "结束通话失败");
            }
        }

        // 获取房间列表
        public async Task GetRooms()
        {
            try
            {
                var rooms = await _roomService.GetAllRoomsAsync();
                var roomList = rooms.Select(r => new 
                { 
                    Id = r.Id, 
                    Name = r.Name, 
                    UserCount = r.UserCount, 
                    MaxUsers = r.MaxUsers,
                    IsFull = r.IsFull,
                    CreatedAt = r.CreatedAt
                }).ToList();
                
                await Clients.Caller.SendAsync("RoomsList", roomList);
                _logger.LogDebug("Sent rooms list to {ConnectionId}, {RoomCount} rooms available", Context.ConnectionId, roomList.Count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting rooms for connection {ConnectionId}", Context.ConnectionId);
                await Clients.Caller.SendAsync("Error", "获取房间列表失败，请重试");
            }
        }

        // 获取房间用户列表
        public async Task GetRoomUsers(string roomId)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(roomId))
                {
                    await Clients.Caller.SendAsync("Error", "房间ID不能为空");
                    return;
                }

                var user = await _userService.GetUserByConnectionIdAsync(Context.ConnectionId);
                if (user == null || user.RoomId != roomId)
                {
                    await Clients.Caller.SendAsync("Error", "您不在该房间中");
                    return;
                }

                var roomUsers = await _roomService.GetRoomUsersAsync(roomId);
                var userList = roomUsers.Select(u => new { u.Id, u.Name, IsCurrentUser = u.Id == user.Id }).ToList();
                
                await Clients.Caller.SendAsync("RoomUsersList", userList);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting room users for room {RoomId} from connection {ConnectionId}", roomId, Context.ConnectionId);
                await Clients.Caller.SendAsync("Error", "获取房间用户列表失败");
            }
        }

        // 心跳检测
        public async Task Ping()
        {
            try
            {
                await Clients.Caller.SendAsync("Pong", DateTime.UtcNow);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error handling ping from connection {ConnectionId}", Context.ConnectionId);
            }
        }

        // 测试方法
        public async Task TestMethod(string message)
        {
            _logger.LogInformation("TestMethod called: message='{Message}', connectionId='{ConnectionId}'", message, Context.ConnectionId);
            
            try
            {
                await Clients.Caller.SendAsync("TestResponse", $"服务器收到: {message}");
                _logger.LogInformation("TestResponse sent successfully to {ConnectionId}", Context.ConnectionId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error sending TestResponse to {ConnectionId}", Context.ConnectionId);
            }
        }

        // 简单的创建房间测试方法
        public async Task CreateRoomTest(string roomName)
        {
            _logger.LogInformation("CreateRoomTest called: roomName='{RoomName}', connectionId='{ConnectionId}'", roomName, Context.ConnectionId);
            
            try
            {
                await Clients.Caller.SendAsync("CreateRoomTestResponse", $"收到创建房间请求: {roomName}");
                _logger.LogInformation("CreateRoomTestResponse sent successfully to {ConnectionId}", Context.ConnectionId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in CreateRoomTest for {ConnectionId}", Context.ConnectionId);
                throw;
            }
        }
    }
} 